package com.zdsoft.site.mina.p2p;

import org.apache.mina.core.session.IoSession;

import com.hundsun.encrypt.util.StringUtil;
import com.zdsoft.site.mina.model.PackageHeader;
import com.zdsoft.site.mina.model.request.AbstractRequest;
import com.zdsoft.site.mina.model.response.ResponseChangeKey;
/**
 * 6.1.33  加密密钥交换(46700) 
 * 说明： 
	1.  本功能适用于银行和服务商直联模式下的软加密方式。 
	2.  本功适用于服务商系统向银行监管系统发送密钥交换，由监管系统生成新的密钥。 
 * @author cqyhm
 * 软加密说明： 
	1.  监管系统对报文和报文中的关键信息使用三级加密方式：密码加密，报文MAC处理和通讯报文加密。对包头信息不进行任何的加密处理。所有交易使用同一种加密方式。 
	2.  监管系统使用标准的DES加密算法。 
	3.  涉及密钥为[*交换密钥、密码密钥、MAC密钥和包文密钥]，其中[*交换密钥]和[报文密钥]为银行和服务商约定的固定密钥。 
	4.  系统创建时，双方初始化各自的[交换密钥和包文密钥]。服务商方通过密钥交换功能，从银行监管系统获取密码密钥和MAC密钥信息。
		在应答包中的密钥信息是使用交换密钥加密的密文。 
	5.  监管系统和服务商方的加密方式通过通讯包头中的3位密码加密标志来标识：
		第一位：密码加密标志，
		第二位：MAC加密标志，
		第三位：报文加密标志。通讯包头详见本文中的2.3.1 
	6.  加密方 
		1)  密码加密，16位字符长度：当标志＝1时，使用交换的密码密钥进行DES加密；当标志＝2时，不加密处理，使用密码原文传输；
			当标志为其他时，则使用固定的密码密钥进行DES加密，此密码密钥需要银行事先和服务商约定。 
		2)  MAC加密，8字符长度：当标志＝0时，不进行MAC处理，包头中的MAC为8位’ ’（空格）；如标志＝1时，则为报文的MAC值。 
		3)  报文加密：当标志＝0时，不进行报文加密处理；如标志＝1时，使用固定的报文密钥进行	全报文DES加密，如标志＝2时，使用固定的报文密钥进行全报文3-DES加密。 
	7.  解密方 
		1)  报文解密：当标志＝0时，不进行报文解密处理；如标志＝1时，根据标志位，使用固定的
			报文密钥进行报文DES解密，还原报文。 
		2)  MAC核对：当标志＝0时，不进行MAC处理；如标志＝1时，使用相应的MAC密钥对报文进行
			DES加密产生新的MAC值，再和包头中的MAC值进行核对。 
		3)  密码解密：当标志＝1时，使用交换的密码密钥进行DES解密；当标志＝2时，直接使用密
			码原文；当标志为其他时，则使用固定的密码密钥进行DES解密。固定的密码密钥需要事
			先和银行约定。 
	8.  当密钥交换失败时，由双方负责初始化各自的密钥值。 	
 */
public class ChangeKeyHandler extends P2PIoHandler {
	
    public ChangeKeyHandler(AbstractRequest request) {
		super(request);
	}

	@Override
	public void sessionOpened(IoSession session) throws Exception {
		logger.debug("打开会话:{}",getInstrCd());
		//包头信息
		PackageHeader pkghdr=new PackageHeader();
    	pkghdr.setInstId(getInstId());
    	pkghdr.setInstrCd(getInstrCd());
    	pkghdr.setFlag("012");
    	pkghdr.setMac(StringUtil.rightPad("0",32,"0"));
    	//包体信息
    	request.getMsgHdr().setInstrCd(getInstrCd());
    	request.getMsgHdr().getSvInst().setInstId(getInstId());
    	request.getMsgHdr().getRqRef().setRefIssr(getInstId());
    	String text=request.toXml();//转换为xml
    	
    	pkghdr.setBodyLength(text.getBytes("GBK").length);
    	session.setAttribute("pkghdr", pkghdr);
    	logger.debug("1.0.打开会话发送报文:{}{}",pkghdr,text);
    	session.write(pkghdr+text);
	}
	@Override
	public void messageReceived(IoSession session, Object message) throws Exception {
		String text=message.toString();
		setResponse(new ResponseChangeKey(text));
		logger.debug("2.4.接收服务端的数据:[{}]", text);//接收的消息已经经过解码器转换为字符串
		ResponseChangeKey response =(ResponseChangeKey)getResponse();
		logger.debug("2.5.接收对象:{}", response);
	}

	@Override
	public String getInstrCd() {
		return "46700";
	}
}
